import java.net.DatagramSocket;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.util.Random;

public class UDPServer {
    public static void main(String[] args) throws Exception {
        String serverIP = args.length > 0 ? args[0] : "0.0.0.0"; //默认绑定所有接口
        int serverPort = args.length > 1 ? Integer.parseInt(args[1]) : 9876; //默认端口9876
        DatagramSocket serverSocket = new DatagramSocket(serverPort, InetAddress.getByName(serverIP));
        byte[] receiveData = new byte[1024];
        Random random = new Random();
        double lossRate = 0.2; //20%丢包率

        System.out.println("服务器运行在 " + serverIP + ":" + serverPort);

        while (true) {
            DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
            serverSocket.receive(receivePacket);
            byte[] data = receivePacket.getData();
            ByteBuffer buffer = ByteBuffer.wrap(data, 0, receivePacket.getLength());

            char command = (char) buffer.get(); //1字节命令
            int sequence = buffer.getInt();     //4字节序列号
            long timestamp = buffer.getLong();  //8字节时间戳
            short dataLength = buffer.getShort(); //2字节数据长度
            byte[] payload = new byte[dataLength];
            buffer.get(payload); //获取数据部分

            String message = new String(payload, "UTF-8");
            System.out.println("接收到: " + message + " [Seq: " + sequence + "] from " + receivePacket.getAddress().getHostAddress());

            if (command == 'C') {
                System.out.println("收到连接请求，发送确认");
                sendAck(serverSocket, receivePacket.getAddress(), receivePacket.getPort(), sequence);
            } else if (command == 'D') {
                if (random.nextDouble() >= lossRate) {
                    sendAck(serverSocket, receivePacket.getAddress(), receivePacket.getPort(), sequence);
                } else {
                    System.out.println("模拟丢包: 序列号 " + sequence);
                }
            }
        }
    }

    private static void sendAck(DatagramSocket socket, InetAddress address, int port, int sequence) throws Exception {
        ByteBuffer buffer = ByteBuffer.allocate(15); // 1 + 4 + 8 + 2
        buffer.put((byte) 'A');          //命令: 确认
        buffer.putInt(sequence);         //序列号
        buffer.putLong(System.currentTimeMillis()); //时间戳
        buffer.putShort((short) 0);      //数据长度为0
        byte[] sendData = buffer.array();
        DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, address, port);
        socket.send(sendPacket);
    }
}